package com.wordplat.quickstart.xutils.db.converter;

import com.wordplat.quickstart.xutils.common.util.LogUtil;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Author: wyouflf
 * Date: 13-11-4
 * Time: 下午10:27
 *
 * @since 2021-05-09
 */
public final class ColumnConverterFactory {
    private static final ConcurrentHashMap<String, ColumnConverter> HASH_MAP;

    private ColumnConverterFactory() {
    }

    /**
     * getColumnConverter
     *
     * @param columnType
     * @return ColumnConverter
     * @throws RuntimeException
     */
    public static ColumnConverter getColumnConverter(Class columnType) {
        ColumnConverter result = null;
        if (HASH_MAP.containsKey(columnType.getName())) {
            result = HASH_MAP.get(columnType.getName());
        } else if (ColumnConverter.class.isAssignableFrom(columnType)) {
            try {
                ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance();
                HASH_MAP.put(columnType.getName(), columnConverter);
                result = columnConverter;
            } catch (Throwable ex) {
                LogUtil.e(ex.getMessage(), ex);
            }
        }

        if (result == null) {
            throw new RuntimeException("Database Column Not Support: " + columnType.getName()
                    + ", please impl ColumnConverter or use ColumnConverterFactory#registerColumnConverter(...)");
        }

        return result;
    }

    /**
     * registerColumnConverter
     *
     * @param columnType
     * @param columnConverter
     */
    public static void registerColumnConverter(Class columnType, ColumnConverter columnConverter) {
        HASH_MAP.put(columnType.getName(), columnConverter);
    }

    /**
     * isSupportColumnConverter
     *
     * @param columnType
     * @return boolean
     */
    public static boolean isSupportColumnConverter(Class columnType) {
        if (HASH_MAP.containsKey(columnType.getName())) {
            return true;
        } else if (ColumnConverter.class.isAssignableFrom(columnType)) {
            try {
                ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance();
                HASH_MAP.put(columnType.getName(), columnConverter);
                return true;
            } catch (Throwable ex) {
                LogUtil.e(ex.getMessage(), ex);
            }
        }
        return false;
    }

    static {
        HASH_MAP = new ConcurrentHashMap<String, ColumnConverter>();

        BooleanColumnConverter booleanColumnConverter = new BooleanColumnConverter();
        HASH_MAP.put(boolean.class.getName(), booleanColumnConverter);
        HASH_MAP.put(Boolean.class.getName(), booleanColumnConverter);

        ByteArrayColumnConverter byteArrayColumnConverter = new ByteArrayColumnConverter();
        HASH_MAP.put(byte[].class.getName(), byteArrayColumnConverter);

        ByteColumnConverter byteColumnConverter = new ByteColumnConverter();
        HASH_MAP.put(byte.class.getName(), byteColumnConverter);
        HASH_MAP.put(Byte.class.getName(), byteColumnConverter);

        CharColumnConverter charColumnConverter = new CharColumnConverter();
        HASH_MAP.put(char.class.getName(), charColumnConverter);
        HASH_MAP.put(Character.class.getName(), charColumnConverter);

        DateColumnConverter dateColumnConverter = new DateColumnConverter();
        HASH_MAP.put(Date.class.getName(), dateColumnConverter);

        DoubleColumnConverter doubleColumnConverter = new DoubleColumnConverter();
        HASH_MAP.put(double.class.getName(), doubleColumnConverter);
        HASH_MAP.put(Double.class.getName(), doubleColumnConverter);

        FloatColumnConverter floatColumnConverter = new FloatColumnConverter();
        HASH_MAP.put(float.class.getName(), floatColumnConverter);
        HASH_MAP.put(Float.class.getName(), floatColumnConverter);

        IntegerColumnConverter integerColumnConverter = new IntegerColumnConverter();
        HASH_MAP.put(int.class.getName(), integerColumnConverter);
        HASH_MAP.put(Integer.class.getName(), integerColumnConverter);

        LongColumnConverter longColumnConverter = new LongColumnConverter();
        HASH_MAP.put(long.class.getName(), longColumnConverter);
        HASH_MAP.put(Long.class.getName(), longColumnConverter);

        ShortColumnConverter shortColumnConverter = new ShortColumnConverter();
        HASH_MAP.put(short.class.getName(), shortColumnConverter);
        HASH_MAP.put(Short.class.getName(), shortColumnConverter);

        SqlDateColumnConverter sqlDateColumnConverter = new SqlDateColumnConverter();
        HASH_MAP.put(java.sql.Date.class.getName(), sqlDateColumnConverter);

        StringColumnConverter stringColumnConverter = new StringColumnConverter();
        HASH_MAP.put(String.class.getName(), stringColumnConverter);
    }
}
